package vip.xiaonuo.issued.task;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.aliyun.oss.common.utils.DateUtil;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
import reactor.core.Reactor;
import vip.xiaonuo.core.timer.TimerTaskRunner;
import vip.xiaonuo.facedoor.iservice.IFaceDoorDtoService;
import vip.xiaonuo.facedoor.modular.device.listener.DeviceChangeTypeEnum;
import vip.xiaonuo.facedoor.modular.device.listener.DevicePublisher;
import vip.xiaonuo.facedoor.modular.device.listener.DeviceSourceEnum;
import vip.xiaonuo.facedoor.modular.devicebase.entity.DeviceBase;
import vip.xiaonuo.facedoor.modular.devicebase.service.DeviceBaseService;

import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;

import vip.xiaonuo.facedoor.modular.devicebase.vo.lock.LockCell;
import vip.xiaonuo.facedoor.rule.DwRulesEngine;
import vip.xiaonuo.facedoor.vo.dewo.DeviceStateResponse;

import javax.annotation.Resource;

@Component
@Slf4j
public class DeviceHeartBeatTask implements TimerTaskRunner {

    private static final CopyOnWriteArraySet<String> currentExecuteTask = new CopyOnWriteArraySet();

    public static Map<String, String> DEVICE_STATE_MAP = new HashMap<String, String>() {
        {
            put("0199", "参数有误：key不能为空");
            put("0299", "开锁失败：key不正确");
            put("0000", "设备状态获取成功");
        }
    };

    @Autowired
    private DeviceBaseService deviceBaseService;

    @Override
    public void action(String jobParams, String taskIds) {
        synchronized (DeviceHeartBeatTask.class) {
            if (currentExecuteTask.contains(jobParams)) {
                log.error("当前任务正在执行请稍后！");
                return;
            }
            log.info("心跳任务开始执行" + jobParams + DateUtil.formatAlternativeIso8601Date(new Date()));
            currentExecuteTask.add(jobParams);
        }
        // 心跳
        heartBeat();
        log.info("心跳任务执行结束" + jobParams);
        currentExecuteTask.remove(jobParams);
    }

    @Override
    @XxlJob("DeviceHeartBeatTask")
    public void executeXxlJob() {
        this.heartBeat();
    }

    private void heartBeat() {
        List<DeviceBase> deviceBases = deviceBaseService.list();
        for (DeviceBase deviceBase : deviceBases) {
            if (StringUtils.isBlank(deviceBase.getCabinetIp()) && StringUtils.isBlank(deviceBase.getCabinetPort())) {
                log.error("设备未设置ip和端口不进行操作!");
                continue;
            }
            if (ObjectUtil.equal(deviceBase.getDeviceType(), "6")) {
                log.debug("访客机心跳 非主动查询!");
                continue;
            }
            if (ObjectUtil.equal(deviceBase.getDeviceType(), "7")) {
                log.debug("8寸人脸一体机心跳 非主动查询!");
                continue;
            }
            if (ObjectUtil.equal(deviceBase.getDeviceType(), "4")) {
                log.debug("掌静脉心跳 非主动查询!");
                continue;
            }
            if (ObjectUtil.equal(deviceBase.getDeviceType(), "10")) {
                log.debug("鸿图设备 单独处理心跳!");
                continue;
            }
            try {
                String uri = IFaceDoorDtoService.getBaseParam(deviceBase.getCabinetIp(), Integer.parseInt(deviceBase.getCabinetPort()));
                DeviceStateResponse deviceStateResponse = DwRulesEngine.faceDoorDtoService.getDeviceState(uri);
                // 设备返回是否异常
                if (deviceStateResponse.getCode().equals("0000")) {
                    deviceBase.setDeviceState("1");
                    deviceBase.setCounter(0);
                    deviceBase.setLastOnlineTime(new Date());
                    deviceBase.setMemberCount(deviceStateResponse.getData().getMemberCount());
                    // 处理存储柜相关数据
                    if (ObjectUtil.equal(deviceBase.getDeviceType(), "5")) {
                        deviceBase.setMaxUseNum(deviceStateResponse.getData().getMaxUsageNum());
                        deviceBase.setAdminPwd(deviceStateResponse.getData().getAdminPwd());
                        deviceBase.setLockCellState(deviceStateResponse.getData().getCabinetStatus());
                    }
                    deviceBaseService.updateById(deviceBase);
//          devicePublisher.publishEvent(DeviceChangeTypeEnum.EDIT, DeviceSourceEnum.BASE,deviceBase);
                } else {
                    deviceBase.setCounter(deviceBase.getCounter() + 1);
                    deviceBaseService.updateById(deviceBase);
                    log.error("设备返回异常【{}】，将设备【{}】计数器+1", DEVICE_STATE_MAP.get(deviceStateResponse.getCode()), deviceBase.getName());
                    downDevice(deviceBase);
                }
            } catch (Exception e) {
                deviceBase.setCounter(Optional.ofNullable(deviceBase.getCounter()).orElse(0) + 1);
                deviceBaseService.updateById(deviceBase);
                log.error("请求接口异常，将设备 【{}】计数器+1 错误信息【{}】", deviceBase.getName(), ExceptionUtils.getMessage(e));
                downDevice(deviceBase);
            }
        }
    }


    private void downDevice(DeviceBase deviceBase) {
        if (deviceBase.getCounter() >= 3) {
            deviceBase.setDeviceState("2");
            deviceBaseService.updateById(deviceBase);
//      devicePublisher.publishEvent(DeviceChangeTypeEnum.EDIT, DeviceSourceEnum.BASE,deviceBase);
            log.error("计数器大于等于3，设备【{}】置为断线", deviceBase.getName());
        }
    }
}
